package com.hqd.jjvm.classpath;

import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.ArrayUtils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 加载class的抽象类
 *
 * @author hqd
 */
@Getter
@Setter
public abstract class AbstractClassResource implements ClassResource {
    private Map<String, ClassFileInfo> classHexMap;
    private List<File> classFileList;
    private String rootPath;
    private String fileSuffix;

    public AbstractClassResource(String rootPath, String fileSuffix) {
        this.classHexMap = new HashMap<>();
        this.classFileList = new LinkedList<>();
        this.rootPath = rootPath;
        this.fileSuffix = fileSuffix;
        init();
    }


    protected void init() {
        this.classFileList = searchFiles(getRootPath(), getFileSuffix(), false);
    }

    protected boolean isWildcardCharacter(String path) {
        return path.endsWith(WILDCARD_CHARACTER) ? true : false;
    }

    /**
     * 读取class文件
     *
     * @param in
     * @return
     */
    protected String readClassFileToStr(InputStream in) {
        try (BufferedInputStream bis = new BufferedInputStream(in)) {
            int code;
            StringBuilder sb = new StringBuilder();
            while ((code = bis.read()) != -1) {
                String temp = Integer.toHexString(code);
                sb.append(temp.length() < 2 ? "0" + temp : temp);
            }
            return sb.toString();

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据后缀名搜索文件
     *
     * @param path
     * @param fileSuffix
     * @param isRecursion
     * @return
     */
    protected List<File> searchFiles(String path, String fileSuffix, boolean isRecursion) {
        List<File> list = new LinkedList<>();
        File file = new File(path);
        if (file.isFile()) {
            if (file.getName().endsWith(fileSuffix)) {
                list.add(file);
            }
        } else {
            File[] files = file.listFiles();
            if (ArrayUtils.isNotEmpty(files)) {
                for (File t : files) {
                    if (t.isFile()) {
                        if (t.getName().endsWith(fileSuffix)) {
                            list.add(t);
                        }
                    } else {
                        if (isRecursion) {
                            list.addAll(searchFiles(t.getPath(), fileSuffix, true));
                        }
                    }
                }
            }
        }
        return list;
    }


    @Override
    public boolean isExists(String classPath) {
        return getClassHexMap().get(classPath) == null ? false : true;
    }
}
